<template>
  <div class="kb-container">
    <div class="kb-header">
      <div class="title-area">
        <h2>知识库管理</h2>
        <el-tag type="success" effect="dark">向量检索支撑RAG</el-tag>
      </div>
      <div class="actions">
        <el-button type="primary" @click="openUpload">上传文档</el-button>
        <el-button :loading="loadingStats" @click="loadStats" plain>刷新统计</el-button>
      </div>
    </div>

    <el-row :gutter="16" class="stats-row">
      <el-col :span="4" v-for="card in statCards" :key="card.key">
        <div class="stat-card">
          <div class="label">{{ card.label }}</div>
          <div class="value">{{ stats[card.key] ?? 0 }}</div>
        </div>
      </el-col>
    </el-row>

    <el-tabs v-model="activeTab" class="kb-tabs" style="margin-top:12px">
      <el-tab-pane label="文档" name="docs">
        <el-table :data="documents" style="width:100%" v-loading="loadingList" size="small" class="kb-table">
          <el-table-column prop="title" label="标题" min-width="160" />
          <el-table-column prop="fileName" label="文件名" min-width="160" />
          <el-table-column prop="fileType" label="类型" width="90" />
          <el-table-column prop="fileSize" label="大小" width="100" />
          <el-table-column prop="chunkCount" label="分块数" width="90" />
          <el-table-column prop="status" label="状态" width="110">
            <template #default="{ row }">
              <el-tag :type="statusType(row.status)" size="small">{{ row.status }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="createdAt" label="上传时间" width="180">
            <template #default="{ row }">{{ formatDate(row.createdAt) }}</template>
          </el-table-column>
          <el-table-column label="操作" width="200" fixed="right">
            <template #default="{ row }">
              <el-button v-if="row.status === 'uploaded' || row.status === 'failed'" link size="small" type="primary"
                @click="process(row)">处理</el-button>
              <el-button link size="small" type="danger" @click="remove(row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-tab-pane>
      <el-tab-pane label="知识条目" name="items">
        <div class="item-filters" style="margin-bottom:8px; display:flex; gap:8px; flex-wrap:wrap">
          <el-input v-model="itemQuery.keyword" placeholder="关键词" clearable @clear="fetchItems" style="width:180px" />
          <el-select v-model="itemQuery.documentId" placeholder="文档" clearable filterable @change="handleDocChange"
            style="width:220px" :loading="loadingDocs">
            <el-option v-for="d in docOptions" :key="d.id" :label="d.title" :value="d.id" />
          </el-select>
          <el-select v-model="itemQuery.documentType" placeholder="类型" clearable @change="handleItemFilterChange"
            style="width:140px">
            <el-option label="全部" value="" />
            <el-option label="txt" value="txt" />
            <el-option label="md" value="md" />
            <el-option label="docx" value="docx" />
            <el-option label="pdf" value="pdf" />
            <el-option label="xls/xlsx" value="xlsx" />
          </el-select>
          <el-button size="small" type="primary" @click="fetchItems">搜索</el-button>
        </div>
        <el-table :data="knowledgeItems" size="small" v-loading="loadingItems" style="width:100%"
          @row-dblclick="openItemDetail">
          <el-table-column prop="title" label="条目标题" min-width="140" />
          <el-table-column prop="chunkIndex" label="块序" width="60" />
          <el-table-column prop="preview" label="内容预览" min-width="300" show-overflow-tooltip />
          <el-table-column prop="documentTitle" label="所属文档" min-width="140" />
          <el-table-column prop="documentType" label="类型" width="70" />
          <el-table-column prop="embeddingType" label="嵌入类型" width="110" />
          <el-table-column prop="source" label="来源" width="80" />
          <el-table-column prop="contentLength" label="长度" width="70" />
          <el-table-column prop="createdAt" label="时间" width="170">
            <template #default="{ row }">{{ formatDate(row.createdAt) }}</template>
          </el-table-column>
          <el-table-column label="操作" width="90">
            <template #default="{ row }">
              <el-button link size="small" @click="openItemDetail(row)">详情</el-button>
            </template>
          </el-table-column>
        </el-table>
        <div style="display:flex; justify-content:center; margin-top:8px">
          <el-pagination :current-page="itemQuery.page" :page-size="itemQuery.pageSize" :total="itemsTotal"
            layout="total, prev, pager, next, jumper" @current-change="p => { itemQuery.page = p; fetchItems() }" />
        </div>
      </el-tab-pane>
    </el-tabs>

    <el-dialog v-model="uploadVisible" title="上传知识库文档" width="600px">
      <el-form :model="uploadForm" label-width="80px">
        <el-form-item label="标题">
          <el-input v-model="uploadForm.title" placeholder="文档标题" />
        </el-form-item>
        <el-form-item label="描述">
          <el-input v-model="uploadForm.description" type="textarea" :rows="2" />
        </el-form-item>
        <el-form-item label="标签">
          <el-input v-model="uploadForm.tags" placeholder="逗号分隔" />
        </el-form-item>
        <el-form-item label="权限">
          <el-select v-model="uploadForm.accessLevel" style="width:100%">
            <el-option label="内部" value="internal" />
            <el-option label="公开" value="public" />
            <el-option label="私有" value="private" />
          </el-select>
        </el-form-item>
        <el-form-item label="文件">
          <el-upload drag :auto-upload="false" :limit="1" :file-list="fileList" :on-change="onFileChange"
            accept=".txt,.pdf,.docx">
            <el-icon class="el-icon--upload">
              <upload />
            </el-icon>
            <div class="el-upload__text">拖拽或点击选择文件</div>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="uploadVisible = false">取消</el-button>
        <el-button type="primary" :loading="uploading" @click="submitUpload">提交</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="itemDetailVisible" title="知识条目详情" width="700px">
      <template v-if="!itemDetail">
        <div class="skeleton-line" style="width:60%"></div>
        <div class="skeleton-line" style="width:40%"></div>
        <div class="skeleton-line" style="width:90%"></div>
        <div class="skeleton-line" style="width:85%"></div>
        <div class="skeleton-line" style="width:92%"></div>
      </template>
      <div v-else>
        <p><b>文档:</b> {{ itemDetail.documentTitle }} (#{{ itemDetail.chunkIndex }})</p>
        <p><b>类型:</b> {{ itemDetail.documentType }} | <b>嵌入:</b> {{ itemDetail.embeddingType }} | <b>维度:</b> {{
          itemDetail.embeddingDimensions }} | <b>长度:</b> {{ itemDetail.contentLength }}</p>
        <p><b>源:</b> {{ itemDetail.source || '-' }} | <b>分块:</b> {{ itemDetail.isChunked ? '是' : '否' }}</p>
        <p
          style="white-space:pre-wrap; background:#0f172a; padding:8px; border-radius:4px; max-height:320px; overflow:auto">
          {{ itemDetail.fullContent }}</p>
      </div>
      <template #footer>
        <el-button @click="itemDetailVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { uploadKnowledge, getKnowledgeList, getKnowledgeStatistics, processKnowledgeDocument, deleteKnowledgeDocument } from '@/api/knowledge'
import { getKnowledgeItems, getKnowledgeItemDetail } from '@/api/knowledgeItems'
import { getKnowledgeSimpleDocs } from '@/api/knowledgeDocs'

const documents = ref([])
const stats = ref({})
const loadingList = ref(false)
const loadingStats = ref(false)
const uploadVisible = ref(false)
const uploading = ref(false)
const fileList = ref([])

const uploadForm = ref({
  title: '',
  description: '',
  tags: '',
  accessLevel: 'internal'
})

const statCards = [
  { key: 'totalDocuments', label: '总文档' },
  { key: 'completedDocuments', label: '已完成' },
  { key: 'processingDocuments', label: '处理中' },
  { key: 'uploadedDocuments', label: '待处理' },
  { key: 'failedDocuments', label: '失败' },
  { key: 'totalChunks', label: '向量块' }
]

const activeTab = ref('docs')
// 知识条目相关 state
const knowledgeItems = ref([])
const loadingItems = ref(false)
const itemsTotal = ref(0)
const itemDetailVisible = ref(false)
const itemDetail = ref(null)
const itemQuery = ref({ keyword: '', documentType: '', documentId: '', page: 1, pageSize: 10 })
const docOptions = ref([])
const loadingDocs = ref(false)

function statusType(status) {
  switch (status) {
    case 'completed': return 'success'
    case 'processing': return 'warning'
    case 'failed': return 'danger'
    default: return 'info'
  }
}

function formatDate(val) {
  if (!val) return ''
  return new Date(val).toLocaleString()
}

async function loadList() {
  loadingList.value = true
  try {
    const { data } = await getKnowledgeList()
    documents.value = data
  } catch (e) {
    ElMessage.error('获取文档列表失败')
  } finally {
    loadingList.value = false
  }
}

async function loadStats() {
  loadingStats.value = true
  try {
    const { data } = await getKnowledgeStatistics()
    stats.value = data
  } catch (e) {
    ElMessage.error('获取统计失败')
  } finally { loadingStats.value = false }
}

function openUpload() {
  uploadForm.value = { title: '', description: '', tags: '', accessLevel: 'internal' }
  fileList.value = []
  uploadVisible.value = true
}

function onFileChange(file, fl) {
  fileList.value = fl.slice(-1)
}

async function submitUpload() {
  if (!uploadForm.value.title) { ElMessage.warning('请输入标题'); return }
  if (fileList.value.length === 0) { ElMessage.warning('请选择文件'); return }
  uploading.value = true
  try {
    const fd = new FormData()
    fd.append('Title', uploadForm.value.title)
    fd.append('Description', uploadForm.value.description)
    fd.append('Tags', uploadForm.value.tags)
    fd.append('AccessLevel', uploadForm.value.accessLevel)
    fd.append('File', fileList.value[0].raw)
    await uploadKnowledge(fd)
    ElMessage.success('上传成功，后台处理中')
    uploadVisible.value = false
    loadList(); loadStats()
  } catch (e) {
    ElMessage.error('上传失败')
  } finally { uploading.value = false }
}

async function process(row) {
  try {
    await processKnowledgeDocument(row.id)
    ElMessage.success('已提交处理')
    loadList(); loadStats()
  } catch { ElMessage.error('提交处理失败') }
}

async function remove(row) {
  try {
    await ElMessageBox.confirm(`确定删除文档: ${row.title}?`, '提示', { type: 'warning' })
    await deleteKnowledgeDocument(row.id)
    ElMessage.success('删除成功')
    loadList(); loadStats()
  } catch (e) {
    if (e !== 'cancel') ElMessage.error('删除失败')
  }
}

async function loadSimpleDocs() {
  loadingDocs.value = true
  try { const { data } = await getKnowledgeSimpleDocs(); docOptions.value = data || [] } finally { loadingDocs.value = false }
}

// augment itemQuery to include documentId
itemQuery.value.documentId = ''

function handleDocChange() { itemQuery.value.page = 1; fetchItems() }

// modify fetchItems to use documentId & show skeleton if first load
const itemsFirstLoad = ref(true)
async function fetchItems() {
  if (activeTab.value !== 'items') return
  loadingItems.value = true
  try {
    const { data } = await getKnowledgeItems({
      keyword: itemQuery.value.keyword || undefined,
      documentType: itemQuery.value.documentType || undefined,
      documentId: itemQuery.value.documentId || undefined,
      page: itemQuery.value.page,
      pageSize: itemQuery.value.pageSize
    })
    knowledgeItems.value = data.items || []
    itemsTotal.value = data.totalCount || 0
  } finally { loadingItems.value = false; itemsFirstLoad.value = false }
}

function handleItemFilterChange() { itemQuery.value.page = 1; fetchItems() }
function openItemDetail(row) {
  itemDetailVisible.value = true
  itemDetail.value = null // reset -> show skeleton
  getKnowledgeItemDetail(row.id).then(r => { itemDetail.value = r.data })
}

watch(activeTab, (v) => { if (v === 'items') { loadSimpleDocs(); fetchItems() } })
onMounted(() => { loadList(); loadStats() })
</script>

<style scoped>
.kb-container {
  padding: 16px;
}

.kb-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.title-area {
  display: flex;
  align-items: center;
  gap: 12px;
}

.stats-row {
  margin-bottom: 16px;
}

.stat-card {
  background: #1f2937;
  padding: 12px 16px;
  border-radius: 8px;
  color: #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .3);
}

.stat-card .label {
  font-size: 12px;
  opacity: .7;
}

.stat-card .value {
  font-size: 22px;
  font-weight: 600;
  margin-top: 4px;
}

.kb-table :deep(.el-tag) {
  text-transform: capitalize;
}

.kb-tabs {
  background: #f5f7fa;
  border-radius: 8px;
  padding: 16px;
}

.item-filters {
  margin-bottom: 16px;
}

/* skeleton styles */
.skeleton-line {
  height: 14px;
  background: linear-gradient(90deg, #1e293b, #334155, #1e293b);
  background-size: 200% 100%;
  animation: skeleton 1.2s infinite;
  border-radius: 4px;
  margin: 6px 0;
}

@keyframes skeleton {
  0% {
    background-position: 0 0;
  }

  100% {
    background-position: -200% 0;
  }
}
</style>